import socket
import json
import threading
import time
from datetime import datetime
import sqlite3
import os


class UDPFeedbackServer:
    def __init__(self, host='0.0.0.0', port=9999):
        """
        初始化UDP反馈服务器

        参数:
            host (str): 服务器监听地址，默认为所有可用接口
            port (int): 服务器监听端口，默认为9999
        """
        self.host = host
        self.port = port
        # 创建UDP套接字
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        # 绑定到指定地址和端口
        self.socket.bind((self.host, self.port))
        self.running = False  # 服务器运行状态标志
        # 存储已连接客户端的映射：{user_id: (ip, port)}
        self.connected_clients = {}
        self.feedback_data = []  # 存储反馈数据的临时列表
        self.init_database()  # 初始化数据库

    def init_database(self):
        """初始化SQLite数据库和表结构"""
        conn = sqlite3.connect('feedback_system.db')
        cursor = conn.cursor()

        # 创建用户反馈表
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS user_feedback (
                id INTEGER PRIMARY KEY AUTOINCREMENT,  
                user_id INTEGER,                      
                username TEXT,                        
                feedback_type TEXT,                  
                title TEXT,                         
                content TEXT,                         
                status TEXT DEFAULT 'pending',        
                admin_response TEXT,                 
                created_at DATETIME DEFAULT CURRENT_TIMESTAMP, 
                updated_at DATETIME DEFAULT CURRENT_TIMESTAMP   
            )
        ''')

        # 创建通知表
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS notifications (
                id INTEGER PRIMARY KEY AUTOINCREMENT, 
                user_id INTEGER,                      
                title TEXT,                           
                content TEXT,                          
                is_read INTEGER DEFAULT 0,             
                created_at DATETIME DEFAULT CURRENT_TIMESTAMP 
            )
        ''')

        conn.commit()
        conn.close()

    def start(self):
        """启动UDP服务器"""
        self.running = True
        print(f"UDP反馈服务器启动在 {self.host}:{self.port}")

        # 启动接收线程（处理入站消息）
        receive_thread = threading.Thread(target=self.receive_messages)
        receive_thread.daemon = True  # 设置为守护线程，主程序退出时自动终止
        receive_thread.start()

        # 启动广播线程（定期检查并发送通知）
        broadcast_thread = threading.Thread(target=self.broadcast_notifications)
        broadcast_thread.daemon = True
        broadcast_thread.start()

    def stop(self):
        """停止UDP服务器"""
        self.running = False
        self.socket.close()  # 关闭套接字
        print("UDP反馈服务器已停止")

    def receive_messages(self):
        """持续接收UDP消息"""
        while self.running:
            try:
                # 接收数据（最大2048字节）
                data, addr = self.socket.recvfrom(2048)
                # 处理接收到的消息
                self.process_message(data.decode('utf-8'), addr)
            except Exception as e:
                if self.running:
                    print(f"接收消息错误: {e}")

    def process_message(self, message, addr):
        """
        处理接收到的JSON格式消息

        参数:
            message (str): 接收到的JSON字符串
            addr (tuple): 客户端地址(IP, port)
        """
        try:
            # 解析JSON数据
            data = json.loads(message)
            msg_type = data.get('type')  # 获取消息类型

            # 合并打印：统一打印消息类型、来源、用户名、用户IP、用户ID（如有）
            user_info = ''
            user_id = None
            if 'data' in data:
                username = data['data'].get('username')
                client_ip = data['data'].get('client_ip')
                user_id = data['data'].get('user_id')
                if username:
                    user_info += f" 用户名: {username}"
                if user_id:
                    user_info += f" 用户ID: {user_id}"
                if client_ip:
                    user_info += f" 用户IP: {client_ip}"
            print(f"收到消息类型: {msg_type} 来自: {addr}{user_info}")

            # 根据消息类型路由到不同的处理函数
            if msg_type == 'feedback_submit':
                self.handle_feedback_submit(data.get('data', {}))
            elif msg_type == 'feedback_response':
                self.handle_feedback_response(data.get('data', {}))
            elif msg_type == 'client_connect':
                self.handle_client_connect(addr, data.get('data', {}))
            elif msg_type == 'client_disconnect':
                self.handle_client_disconnect(addr, data.get('data', {}))
            elif msg_type == 'heartbeat':
                self.handle_heartbeat(addr, data.get('data', {}))
            elif msg_type == 'admin_response_notification':
                self.handle_admin_response_notification(data.get('data', {}))
            else:
                print(f"未知消息类型: {msg_type}")

        except json.JSONDecodeError:
            print(f"无效的JSON消息: {message}")
        except Exception as e:
            print(f"处理消息错误: {e}")

    def handle_feedback_submit(self, feedback_data):
        """
        处理用户提交的反馈

        参数:
            feedback_data (dict): 包含反馈信息的字典
        """
        try:
            # 连接到数据库
            conn = sqlite3.connect('feedback_system.db')
            cursor = conn.cursor()

            # 插入反馈到数据库
            cursor.execute('''
                INSERT INTO user_feedback (user_id, username, feedback_type, title, content)
                VALUES (?, ?, ?, ?, ?)
            ''', (
                feedback_data.get('user_id'),
                feedback_data.get('username'),
                feedback_data.get('feedback_type'),
                feedback_data.get('title'),
                feedback_data.get('content')
            ))

            # 获取新创建的反馈ID
            feedback_id = cursor.lastrowid
            conn.commit()
            conn.close()

            # 广播新反馈通知给管理员
            self.broadcast_to_admin({
                'type': 'new_feedback',
                'data': {
                    'feedback_id': feedback_id,
                    'user_id': feedback_data.get('user_id'),
                    'username': feedback_data.get('username'),
                    'feedback_type': feedback_data.get('feedback_type'),
                    'title': feedback_data.get('title'),
                    'content': feedback_data.get('content'),
                    'created_at': datetime.now().isoformat()
                }
            })

            print(f"收到用户反馈: {feedback_data.get('title')}")

        except Exception as e:
            print(f"处理反馈提交错误: {e}")

    def handle_feedback_response(self, response_data):
        """
        处理管理员对反馈的回复

        参数:
            response_data (dict): 包含回复信息的字典
        """
        try:
            conn = sqlite3.connect('feedback_system.db')
            cursor = conn.cursor()

            # 更新反馈状态和回复内容
            cursor.execute('''
                UPDATE user_feedback 
                SET status = ?, admin_response = ?, updated_at = CURRENT_TIMESTAMP
                WHERE id = ?
            ''', (
                'responded',  # 更新状态为"已回复"
                response_data.get('admin_response'),
                response_data.get('feedback_id')
            ))

            # 创建用户通知
            cursor.execute('''
                INSERT INTO notifications (user_id, title, content)
                VALUES (?, ?, ?)
            ''', (
                response_data.get('user_id'),
                f"反馈回复: {response_data.get('feedback_title')}",
                response_data.get('admin_response')
            ))

            conn.commit()
            conn.close()

            # 广播通知给用户
            self.broadcast_notification_to_user(response_data.get('user_id'), {
                'type': 'feedback_response',
                'data': {
                    'feedback_id': response_data.get('feedback_id'),
                    'feedback_title': response_data.get('feedback_title'),
                    'admin_response': response_data.get('admin_response'),
                    'timestamp': datetime.now().isoformat()
                }
            })

            print(f"管理员回复了反馈: {response_data.get('feedback_title')}")

        except Exception as e:
            print(f"处理反馈回复错误: {e}")

    def handle_admin_response_notification(self, notification_data):
        """
        处理来自Flask应用的管理员回复通知

        参数:
            notification_data (dict): 包含通知信息的字典
        """
        try:
            user_id = notification_data.get('user_id')
            # print(f"收到管理员回复通知，用户ID: {user_id}")
            self.send_notification_to_user(user_id, {
                'type': 'feedback_response_notification',
                'data': {
                    'feedback_id': notification_data.get('feedback_id'),
                    'feedback_title': notification_data.get('feedback_title'),
                    'admin_response': notification_data.get('admin_response'),
                    'admin_username': notification_data.get('admin_username'),
                    'timestamp': datetime.now().isoformat()
                }
            })
        except Exception as e:
            print(f"处理管理员回复通知错误: {e}")

    def handle_client_connect(self, addr, data):
        user_id = data.get('user_id')
        if user_id:
            self.connected_clients[user_id] = addr
            # print(f"客户端连接: {addr} - 用户ID: {user_id}")
            # print(f"当前连接的用户: {list(self.connected_clients.keys())}")

    def handle_client_disconnect(self, addr, data):
        user_id = data.get('user_id')
        if user_id and user_id in self.connected_clients:
            del self.connected_clients[user_id]
            # print(f"客户端断开: {addr} - 用户ID: {user_id}")

    def handle_heartbeat(self, addr, data):
        user_id = data.get('user_id')
        if user_id:
            self.connected_clients[user_id] = addr
            # print(f"收到心跳: {addr} - 用户ID: {user_id}")

    def broadcast_to_admin(self, message):
        """
        广播消息给管理员（此处为预留接口）

        参数:
            message (dict): 要广播的消息字典
        """
        try:
            message_str = json.dumps(message).encode('utf-8')
            # 实际应用中应添加管理员客户端的特殊处理逻辑
            print(f"广播给管理员: {message}")
        except Exception as e:
            print(f"广播给管理员错误: {e}")

    def send_notification_to_user(self, user_id, notification):
        """
        发送通知给特定用户

        参数:
            user_id (int): 目标用户ID
            notification (dict): 通知内容字典
        """
        try:
            if user_id in self.connected_clients:
                client_addr = self.connected_clients[user_id]
                message_str = json.dumps(notification).encode('utf-8')

                try:
                    # 发送UDP数据报到客户端
                    self.socket.sendto(message_str, client_addr)
                    print(f"成功发送通知给用户 {user_id} 到 {client_addr}")
                except Exception as e:
                    print(f"发送通知到用户 {user_id} 失败: {e}")
                    # 移除失效的连接
                    del self.connected_clients[user_id]
            else:
                print(f"用户 {user_id} 未连接，无法发送通知")

        except Exception as e:
            print(f"发送通知错误: {e}")

    def broadcast_notification_to_user(self, user_id, notification):
        """兼容旧接口的广播方法"""
        self.send_notification_to_user(user_id, notification)

    def broadcast_notifications(self):
        """定期检查并广播未读通知"""
        while self.running:
            try:
                # 检查数据库中的未读通知
                conn = sqlite3.connect('feedback_system.db')
                cursor = conn.cursor()

                cursor.execute('''
                    SELECT * FROM notifications WHERE is_read = 0
                ''')

                unread_notifications = cursor.fetchall()
                conn.close()

                # 发送所有未读通知
                if unread_notifications:
                    for notification in unread_notifications:
                        notification_data = {
                            'type': 'notification',
                            'data': {
                                'id': notification[0],
                                'user_id': notification[1],
                                'title': notification[2],
                                'content': notification[3],
                                'created_at': notification[5]
                            }
                        }
                        self.send_notification_to_user(notification[1], notification_data)

            except Exception as e:
                print(f"广播通知错误: {e}")

            time.sleep(10)  # 每10秒检查一次

    def get_feedback_list(self):
        """从数据库获取所有反馈列表"""
        try:
            conn = sqlite3.connect('feedback_system.db')
            cursor = conn.cursor()

            cursor.execute('''
                SELECT * FROM user_feedback ORDER BY created_at DESC
            ''')

            feedbacks = cursor.fetchall()
            conn.close()

            return feedbacks
        except Exception as e:
            print(f"获取反馈列表错误: {e}")
            return []


if __name__ == "__main__":
    server = UDPFeedbackServer()
    try:
        server.start()
        # 主线程循环保持程序运行
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        print("正在停止UDP反馈服务器...")
        server.stop()